package com.dylan.magic.mybatis.pagehelper.storage.dao;

import com.alibaba.fastjson.JSON;
import com.dylan.magic.mybatis.pagehelper.config.db.InsertSelectiveUseGeneratedKeysMapper;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import tk.mybatis.mapper.common.Mapper;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author : ankang
 * @date : 2019/12/13 15:57
 * @Description :
 */
public abstract class BaseDao<T> {
    private Logger logger = LoggerFactory.getLogger(BaseDao.class);

    @Autowired
    protected Mapper<T> mapper;

    protected Mapper<T> getMapper() {
        return mapper;
    }

    /**
     * 查询全部
     */
    protected List<T> selectAll() {
        return mapper.selectAll();
    }

    /**
     * 统计数量
     * 需要使用，由子类放开权限
     * @param entity 不为null的字段为筛选条件,且用等号(=)查询
     */
    protected int selectCount(T entity) {
        if (isEmptyPo(entity)) {
            logger.warn("查询时，实体为空对象");
            return 0;
        }
        return mapper.selectCount(entity);
    }

    /**
     * 查询一个结果,如果有多个返回则抛异常
     * 需要使用，由子类放开权限
     * @param entity 不为null的字段为筛选条件,且用等号(=)查询
     */
    protected T selectOne(T entity) {
        if (isEmptyPo(entity)) {
            logger.warn("查询时，实体为空对象");
            return null;
        }
        return mapper.selectOne(entity);
    }

    /**
     * 查询多个结果
     * 需要使用，由子类放开权限
     * @param entity 不为null的字段为筛选条件,且用等号(=)查询
     */
    protected List<T> select(T entity) {
        if (isEmptyPo(entity)) {
            logger.warn("查询时，实体为空对象");
            return Lists.newArrayListWithCapacity(0);
        }
        return mapper.select(entity);
    }

    /**
     * 用主键查询,model中必须有主键注解字段(@Id)
     * @param key 主键
     */
    public T selectByKey(Object key) {
        return mapper.selectByPrimaryKey(key);
    }

    /**
     * 插入一条记录
     * @param entity 不为null的字段将被插入到数据库
     */
    public int insert(T entity) {
        return mapper.insertSelective(entity);
    }

    /**
     * 插入一条记录,并获取自增ID
     * @param entity 不为null的字段将被插入到数据库
     */
    public int insertUseGeneratedKey(T entity) {
        // 如果该mapper没有继承InsertSelectiveUseGeneratedKeysMapper接口,则调用insertSelective方法,不会返回自增主键
        if (mapper instanceof InsertSelectiveUseGeneratedKeysMapper) {
            return ((InsertSelectiveUseGeneratedKeysMapper) mapper).insertSelectiveUseGeneratedKeys(entity);
        } else {
            logger.debug("没有继承InsertSelectiveUseGeneratedKeysMapper接口");
            return insert(entity);
        }
    }

    /**
     * 用主键删除一条记录,model中必须有主键注解字段(@Id)
     * @param key 主键
     */
    public int deleteByKey(Object key) {
        return mapper.deleteByPrimaryKey(key);
    }

    /**
     * 用主键更新一条记录,model中必须有主键注解字段(@Id)
     * @param entity 主键字段不能为空,其它不为null的字段将被更新
     */
    public int updateByKey(T entity) {
        return mapper.updateByPrimaryKeySelective(entity);
    }

    /**
     * 按条件查询
     * @param example 条件
     */
    public List<T> selectByExample(Object example) {
        return mapper.selectByExample(example);
    }

    /**
     * 按条件统计数量
     * @param example 条件
     */
    public int selectCountByExample(Object example) {
        return mapper.selectCountByExample(example);
    }

    /**
     * 是否为空对象
     */
    private boolean isEmptyPo(Object po) {
        boolean empty = true;
        if (po == null) {
            return empty;
        }
        BeanMap beanMap = BeanMap.create(po);
        for (Object key : beanMap.keySet()) {
            if (beanMap.get(key) != null) {
                empty = false;
                break;
            }
        }
        return empty;
    }
}
